#ifndef SH_UTILITY_DESTRUCT_HPP
#define SH_UTILITY_DESTRUCT_HPP

#include <functional>

#define SH_MAKE_DESTRUCT(callback) sh::Destruct([&]{ callback; })

namespace sh {

    // Destructor callback
    struct Destruct {
        Destruct(std::function<void()> fn) : onDestruct{ fn } {}
        Destruct(Destruct const& obj) : onDestruct{ obj.onDestruct } {}
        Destruct(Destruct&& obj) : onDestruct{ std::move(obj.onDestruct) } {}
        ~Destruct();
        std::function<void()> release();
    private:
        std::function<void()> onDestruct;
    };


    /*
    * //////////////////////////////////////////////////////////////////////////////////////////
    *
    *
    *
    * //////////////////////////////////////////////////////////////////////////////////////////
    */

    inline
        Destruct::~Destruct()
    {
        if (onDestruct)
            onDestruct();
    }

    inline
        std::function<void()>
        Destruct::release()
    {
        std::function<void()> fn;
        fn.swap(onDestruct);
        return fn;
    }

} // namespace sh

#endif // SH_UTILITY_DESTRUCT_HPP
